<template>
	<view :class="pageClass" :style="pageStyle" v-if="pageReady" style="background-color: #F5F5F5;">
		<moxi-nav :set="navSet"></moxi-nav>
		<view class="ai_voice" :style="{ '--bg-color': app_color }" v-if="chooseVoiceList.length > 0">
			<view class="topNav">
				<u-tabs :lineColor="app_color" @click="chooseType" :list="tabsList"
					:scrollable="tabsList.length > 4 ? true : false">
					<!-- <view slot="right" style="padding-left: 4px;">
						<u-icon name="list" color="#999" size="20" @tap="$u.toast('插槽被点击')"></u-icon>
					</view> -->
				</u-tabs>
			</view>
			<view class="classify">
				<view class="tabList">
					<view class="tabItem" :class="item.name == classifyId ? 'active' : ''"
						:style="{ 'background-color': colorList[17], 'color': app_color }" v-for="item in classifyList"
						@click="chooseClassify(item.name)">{{ item.name }}</view>
				</view>
			</view>
			<view class="scrollY">
				<scroll-view scroll-y :scroll-top="scrollTop" @scroll="scroll" style="height: 100%; flex: 1;">
					<view class="chooseVoice con">
						<scroll-view scroll-y :style="{ height: `${tempVoiceList.length <= 4 ? 158 : 224}px` }"
							:scroll-top="voiceListTop" @scroll="scrollVoiceList" v-if="tempVoiceList.length > 0">
							<view class="voiceList">
								<view class="voiceItem" v-for="item in tempVoiceList" :key="item.speakerId"
									:class="voiceId == item.speakerId ? 'action' : ''" @click="chooseVoice(item)">
									<view class="showImg"
										:style="{ border: voiceId == item.speakerId ? 'none' : '1px solid #fff' }">
										<image v-if="voiceId != item.speakerId" class="imageCss" :src="item.img"
											mode="scaleToFill" />
										<view @click="openVoiceTest(voiceData)"
											style=" background-color: #fff; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;"
											v-else>
											<u-icon :name="playStatus ? 'pause' : 'play-right-fill'" :color="app_color"
												size="20"></u-icon>
										</view>
									</view>
									<view>
										<view class="title u-line-1">{{ item.speechType }}</view>
										<view class="name u-line-1">{{ item.speaker }}</view>
									</view>
									<view class="commend" v-if="item.tag">{{ item.tag }}</view>
								</view>
							</view>
						</scroll-view>
						<view v-else>
							<u-empty></u-empty>
						</view>
					</view>
					<view class="setting con">
						<view class="settingItem" v-for="(item, index) in aiSettingInfo" :key="index">
							<view class="title">{{ item.name }}:</view>
							<view class="slider"><u-slider :key="index" v-model="item.value" :min="item.min"
									:max="item.max" :step="item.step" :activeColor="app_color"></u-slider></view>
							<view class="number">
								<u-number-box v-model="item.value" integer :step="item.step" :min="item.min"
									:max="item.max" disabledInput :buttonSize="24" :inputWidth="40"
									iconStyle="font-size: 12px"></u-number-box>
							</view>
						</view>
						<!-- 合成文件格式选择 -->
						<view class="settingItem" style="height: 38px;">
							<view class="title">格式:</view>
							<view class="mleft-16" style="flex: 1; overflow: hidden;">
								<scroll-view scroll-x @scroll="firstScroll" :scroll-left="firstLeft">
									<u-radio-group v-model="userAiSettingInfo.format" placement="row">
										<u-radio :customStyle="{ marginRight: '12px' }"
											v-for="(item, index) in formatList" :key="index" :label="item.name"
											:name="item.name" @change="firstChange">
										</u-radio>
									</u-radio-group>
								</scroll-view>
							</view>
						</view>
						<!-- 合成文件采样率选择 -->
						<view class="settingItem" style="height: 38px;">
							<view class="title">采样率:</view>
							<view class="mleft-16" style="flex: 1; overflow: hidden;">
								<scroll-view scroll-x @scroll="secondScroll" :scroll-left="secondLeft">
									<u-radio-group v-model="userAiSettingInfo.sample_rate" placement="row">
										<u-radio :customStyle="{ marginRight: '12px' }"
											v-for="(item, index) in sample_rateList" :key="index" :label="item.name"
											:name="item.name" @change="secondChange">
										</u-radio>
									</u-radio-group>
								</scroll-view>
							</view>
						</view>
						<!-- 情感 -->
						<view class="settingItem" v-if="emotions[0].length > 0" @click="emotionsShow = true"
							style="justify-content: space-between; padding: 8px 0; cursor: pointer;">
							<view class="title">情感:</view>
							<view class="mleft-16" style="margin: 0 auto 0 0;">{{ emotionsStr }}</view>
							<view>
								<u-icon name="arrow-right" color="#999" size="16"></u-icon>
							</view>
						</view>
					</view>
					<view class="contentInput con">
						<view class="top">
							<view class="money">
								<view>每天上限:</view>
								<view v-if="systemSetting.day_num == 0" style="color: #02cd68;">不限</view>
								<view v-else>{{ systemSetting.day_num }}</view>
							</view>
							<view class="money" @click="navto('/plugin_tts/voice_manage')" style="gap: 0">
								<view :style="{ color: app_color }">历史记录</view>
								<view>
									<u-icon size="16" name="arrow-right" :color="app_color"></u-icon>
								</view>
							</view>
						</view>
						<view class="textArea"
							:style="{ '--text-color': content.length == text_num ? '#EA2121' : Math.floor(text_num / 2) <= content.length ? '#FF8B01' : '#999' }">
							<!-- #ifndef MP-ALIPAY -->
							<u--textarea v-model="content" placeholder="在这里输入你想要生成的语音句子" :maxlength="text_num"
								:placeholderStyle="{ color: '#999999' }" height="88" count></u--textarea>
							<!-- #endif -->
							<!-- #ifdef MP-ALIPAY -->
							<textarea class="alipayText" v-model="content" placeholder="在这里输入你想要生成的语音句子"
								:maxlength="text_num" />
							<!-- #endif -->
						</view>
						<view class="controll">
							<view class="tip" v-if="!content">生成内容需要消耗一定积分</view>
							<view class="tip" v-else style="color:#FF8B01">本次合成需要消耗&emsp;{{ systemSetting.price
							}}&emsp;积分</view>
							<view @click="clearContent" v-if="content.length > 0"
								style="padding: 0 8px; border: 1px solid #EA2121; border-radius: 4px; font-size: 14px; color: #EA2121;">
								<view>清空</view>
							</view>
						</view>
					</view>
				</scroll-view>
			</view>
			<view class="btnArea">
				<view class="btn" :style="{ color: '#fff', backgroundColor: content ? app_color : '#ccc' }"
					@click="openVoiceTaskShow">在线合成</view>
			</view>
		</view>
		<!-- 情感选择器 -->
		<!-- #ifdef MP-BAIDU -->
		<view v-show="emotionsShow">
			<!-- #endif -->
			<view>
				<u-picker :show="emotionsShow" :columns="emotions" v-model="userAiSettingInfo.emotions"
					@confirm="confirm" @cancel="closeShow" closeOnClickOverlay @close="closeShow"
					keyName="name"></u-picker>
			</view>
			<!-- #ifdef MP-BAIDU -->
		</view>
		<!-- #endif -->
		<!-- 任务名称输入 -->

		<!-- #ifdef MP-BAIDU -->
		<view v-show="voiceTaskShow">
			<!-- #endif -->
			<view>
				<u-popup :show="voiceTaskShow" :safeAreaInsetBottom="false" :overlayStyle="{ zIndex: '2' }" :zIndex="3"
					mode="center" round="10" @close="closeShow" closeable closeOnClickOverlay>
					<view class="taskName">
						<view class="title">请输入任务名称</view>
						<view>
							<u--input type="text" placeholder="请输入任务名称" maxlength="14" border="surround"
								v-model="userAiSettingInfo.name"></u--input>
						</view>
						<view>
							<view class="btn" :style="{ color: app_color, borderColor: app_color }" @click="submit">确认合成
							</view>
						</view>
					</view>
				</u-popup>
			</view>
			<!-- #ifdef MP-BAIDU -->
		</view>
		<!-- #endif -->
	</view>
</template>

<script>
export default {
	data() {
		return {
			typeId: '全部',
			classifyId: '全部',
			voiceId: '',
			tabsList: [],
			classifyList: [
				{
					name: '全部',
				},
				{
					name: '精品',
				},
				{
					name: '标准',
				},
				{
					name: '普通',
				}
			],
			chooseVoiceList: [],
			tempVoiceList: [],
			aiSettingInfo: [
				{ name: '音量', min: 0, max: 100, value: 50, step: 1, unit: '' },
				{ name: '音调', min: -500, max: 500, value: 0, step: 1, unit: '' },
				{ name: '语速', min: -500, max: 500, value: 0, step: 1, unit: '' },
			],
			formatList: [
				{ name: 'pcm' },
				{ name: 'mp3', },
				{ name: 'wav', }
			],
			sample_rateList: [{ name: '8000' }, { name: '16000' }],
			money: 0,
			content: '',
			systemSetting: {
				day_num: 0,
				status: 0,
				price: '',
			},
			text_num: 1000, // 语音生成句子最大字数
			scrollTop: 0, // 页面滚动
			voiceListTop: 0, // 语音列表顶部距离
			old: {
				scrollTop: 0,
				voiceListTop: 0,
			},
			userAiSettingInfo: {
				name: '',
				text: '',
				desc: '',
				format: 'mp3',
				voice: 0,
				volume: 0,
				speech_rate: 0,
				pitch_rate: 0,
				sample_rate: '16000',
				emotions: ''
			},
			emotions: [
				[]
			],
			emotionsStr: '', // 中文
			voiceData: {},
			emotionsShow: false,
			voiceTaskShow: false, // 语音生成记录名称
			innerAudioContext: null, // 音频实例
			playStatus: false, // 播放状态
			audioUrl: '',
			speedMoney: 0, // 生成价格
			firstLeft: 0,
			secondLeft: 0,
			old: {
				firstLeft: 0,
				secondLeft: 0,
			}
		};
	},
	onLoad() {
		this.get();
	},
	methods: {
		firstChange(name) {
			const index = this.formatList.findIndex(item => item.name === name);
			if (index == 0) {
				this.goFirstLeft('left')
			} else if (index == this.formatList.length - 1) {
				this.goFirstLeft('right');
			}
		},
		secondChange(name) {
			const index = this.sample_rateList.findIndex(item => item.name === name);
			if (index == 0) {
				this.goSecondLeft('left')
			} else if (index == this.sample_rateList.length - 1) {
				this.goSecondLeft('right');
			}
		},
		firstScroll(e) {
			this.old.firstLeft = e.detail.scrollLeft
		},
		secondScroll(e) {
			this.old.secondLeft = e.detail.scrollLeft
		},
		goFirstLeft(name) {
			this.firstLeft = this.old.firstLeft
			this.$nextTick(function () {
				if (name == 'left') {
					this.firstLeft = 0
				} else if (name == 'right') {
					this.firstLeft = 9999
				}
			});
		},
		goSecondLeft(name) {
			this.secondLeft = this.old.secondLeft
			this.$nextTick(function () {
				if (name == 'left') {
					this.secondLeft = 0
				} else if (name == 'right') {
					this.secondLeft = 9999
				}
			});
		},
		openVoiceTest(item) {
			// 判断该音色需要情感
			if (item.emotions.length > 0 && !this.userAiSettingInfo.emotions) {
				// 如果需要情感,用户需要提交情感才能试听
				this.msg('请选择情感');
				return;
			}
			if (!this.audioUrl) {
				this.getVoice(item.speakerId, this.userAiSettingInfo.emotions);
			} else {
				this.playAudio(this.audioUrl);
			}
		},
		// 获取试听音色url
		getVoice(name, emotion) {
			this.moxiPost(
				'/plugin/tts/user/combineai/start_listen',
				{ name: name, emotion: emotion },
				(res) => {
					this.audioUrl = res.data;
					this.playAudio(this.audioUrl);
				}
			)
		},
		// 播放音频
		playAudio(url) {
			this.playStatus = !this.playStatus;
			// 切换播放内容，重置状态
			if (!this.innerAudioContext) {
				this.innerAudioContext = uni.createInnerAudioContext();
				this.innerAudioContext.src = url;
			}

			// 继续或暂停播放
			if (this.playStatus) {
				this.innerAudioContext.play();
				this.msg('正在试听中...');
			} else {
				this.innerAudioContext.pause();
				this.msg('暂停播放');
			}

			// 监听音频播放结束事件
			this.innerAudioContext.onEnded(() => {
				this.playStatus = false;
				this.msg('试听播放结束');
				this.clearInnerAudioContext();
			});

			// 监听播放错误事件
			this.innerAudioContext.onError((err) => {
				console.error('播放失败:', err);
			});
		},
		openVoiceTaskShow() {
			if (this.content.length == 0) {
				this.msg('请输入需要合成的内容');
				return;
			};
			if (this.voiceData.emotions.length > 0 && !this.userAiSettingInfo.emotions) {
				this.msg('请选择情感');
				return;
			};
			this.userAiSettingInfo.name = '';
			this.voiceTaskShow = true;
		},
		submit() {
			this.userAiSettingInfo.text = this.content;
			if (this.userAiSettingInfo.name.length == 0) {
				this.msg('请输入任务名称');
				return;
			}
			this.userAiSettingInfo.voice = this.voiceId;// 音色
			this.userAiSettingInfo.volume = Math.floor(this.aiSettingInfo[0].value); //音量
			this.userAiSettingInfo.pitch_rate = Math.floor(this.aiSettingInfo[1].value); // 音调
			this.userAiSettingInfo.speech_rate = Math.floor(this.aiSettingInfo[2].value);// 语速
			console.log('data', this.userAiSettingInfo);
			this.moxiPost(
				'/plugin/tts/user/combineai/created_mission',
				this.userAiSettingInfo,
				(res) => {
					this.msg(res.hint);
					this.navto('/plugin_tts/voice_manage');
				},
			)
			this.closeShow();
		},
		confirm(e) {
			this.userAiSettingInfo.emotions = e.value[0].id;
			this.emotionsStr = e.value[0].name;
			// 清除试听音频实例
			this.clearInnerAudioContext();
			this.closeShow();
		},
		closeShow() {
			this.emotionsShow = false;
			this.voiceTaskShow = false;
		},
		scrollVoiceList(e) {
			this.old.voiceListTop = e.detail.scrollTop
		},
		goVoiceListTop(e) {
			this.voiceListTop = this.old.voiceListTop
			this.$nextTick(() => {
				this.voiceListTop = 0
			});
		},
		// 分类数据
		getClassify() {
			// 如果一二级分类都等于全部，那么就显示所有数据 减少循环次数
			if (this.typeId == this.tabsList[0].name && this.classifyId == this.classifyList[0].name) {
				this.tempVoiceList = this.chooseVoiceList;
				if (this.tempVoiceList.length > 0) this.chooseVoice(this.tempVoiceList[0]);
				return;
			}
			// 如果一级分类等于全部，那么就显示二级分类的数据
			this.tempVoiceList = [];
			this.chooseVoiceList.forEach(item => {
				if ((item.scene == this.typeId || this.typeId == this.tabsList[0].name) && (item.tag == this.classifyId || this.classifyId == this.classifyList[0].name || (this.classifyId == '普通' && !item.tag))) {
					this.tempVoiceList.push(item);
				}
			})
			if (this.tempVoiceList.length > 0) this.chooseVoice(this.tempVoiceList[0]);
		},
		get() {
			this.moxiPost(
				'/plugin/tts/user/info/get_list',
				(res) => {
					this.money = this.userinfo.money
					// 重置表单
					this.tabsList = [];
					this.chooseVoiceList = res.data;
					this.systemSetting = res.power;
					if (res.scene.length == 0) return;
					res.scene.forEach(item => {
						this.tabsList.push({
							name: item,
						})
					})
					this.typeId = this.tabsList[0].name;
					this.classifyId = this.classifyList[0].name;
					this.getClassify();
				}
			)
		},
		scroll(e) {
			this.old.scrollTop = e.detail.scrollTop
		},
		goTop(e) {
			this.scrollTop = this.old.scrollTop
			this.$nextTick(() => {
				this.scrollTop = 0
			});
		},
		chooseType(e) {
			if (this.typeId == e.name) return;
			this.typeId = e.name;
			this.classifyId = this.classifyList[0].name;
			this.voiceId = '';
			this.voiceData = {};
			this.emotions = [[]];
			this.goVoiceListTop();
			this.getClassify();
			this.goTop();
		},
		chooseClassify(name) {
			this.classifyId = name;
			this.voiceId = '';
			this.voiceData = {};
			this.emotions = [[]];
			this.goVoiceListTop();
			this.getClassify();
		},
		chooseVoice(item) {
			this.voiceId = item.speakerId;
			this.voiceData = item;
			this.emotions = [[]];
			this.userAiSettingInfo.emotions = '';
			this.emotionsStr = '点击选择';
			if (item.emotions.length > 0) {
				// item.emotions = [{xxxx:aaaa}, {xxx:bbb}] 改造成['aaaa', 'bbb']
				item.emotions.forEach(item => {
					this.emotions[0].push({ id: Object.keys(item)[0], name: Object.values(item)[0] })
				})
			}
			this.sample_rateList.forEach((i, index) => {
				if (parseInt(i.name) > parseInt(item.sampleRate)) {
					// 如果当前的采样率大于item的采样率，那么就删除
					this.sample_rateList.splice(index, 1);
					this.userAiSettingInfo.sample_rate = this.sample_rateList[index - 1].name;
				}
			})
			// 如果当前采样率列表中没有当前的采样率，那么就添加
			if (!this.sample_rateList.some(i => i.name === item.sampleRate.toString())) {
				this.sample_rateList.push({ name: item.sampleRate.toString() });
			}

			// 清除试听音频实例
			this.clearInnerAudioContext();
		},
		clearContent() {
			if (!this.content) return;
			this.isBox('是否清除内容', () => {
				this.content = '';
			}, '清除后将无法撤回');
		},
		clearInnerAudioContext() {
			if (this.innerAudioContext) {
				this.innerAudioContext.stop();
				this.innerAudioContext.destroy();
				this.innerAudioContext = null;
				this.playStatus = false;
				this.audioUrl = '';
			}
		}
	},
}
</script>

<style lang="scss" scoped>
@mixin flex($gap: 8px, $ju: space-between, $al: center, $fd: row, $wrap: nowrap) {
	display: flex;
	justify-content: $ju;
	align-items: $al;
	gap: $gap;
	flex-wrap: $wrap;
	flex-direction: $fd;
}

.ai_voice {
	flex: 1;
	margin-top: 12px;
	@include flex(12px, normal, normal, column);
	overflow: hidden;

	&>view {
		padding: 0 8px;
	}

	.classify {
		.tabList {
			@include flex(8px, normal);
			overflow: scroll hidden;

			.tabItem {
				white-space: nowrap;
				padding: 4px 24px;
				border-radius: 99px;
				font-size: 12px;

				&.active {
					background-color: var(--bg-color) !important;
					color: #fff !important;
				}
			}
		}
	}

	.scrollY {
		flex: 1;
		display: flex;
		overflow: hidden;

		.con {
			margin-bottom: 12px;
			padding: 16px;
			background-color: #fff;
			border-radius: 8px;

			&:last-child {
				margin-bottom: 0;
			}
		}

		.chooseVoice {
			overflow: hidden;

			.voiceList {
				display: grid;
				grid-template-columns: 1fr 1fr;
				grid-template-rows: 1fr 1fr;
				gap: 8px;

				.voiceItem {
					padding: 20px;
					background-color: #F5F5F5;
					border-radius: 8px;
					@include flex(8px, normal);
					position: relative;

					&.action {
						background-color: var(--bg-color);
						color: #fff;

						.name {
							color: #fff;
						}

						.commend {
							background-color: #fff;
							color: var(--bg-color);
						}
					}

					.showImg {
						flex-shrink: 0;
						width: 32px;
						height: 32px;
						border-radius: 50%;
						overflow: hidden;

						.imageCss {
							width: 100%;
							height: 100%;
						}
					}

					.title {
						font-size: 14px;
					}

					.name {
						font-size: 12px;
						color: #666;
					}

					.commend {
						position: absolute;
						display: inline-flex;
						right: 4px;
						top: 4px;
						border-radius: 4px;
						color: #fff;
						padding: 0 8px;
						font-size: 10px;
						background-color: var(--bg-color);
					}
				}
			}
		}

		.setting {
			padding: 16px;
			border-radius: 8px;
			background-color: #fff;
			font-size: 12px;

			.settingItem {
				@include flex(8px, normal);
				margin-bottom: 12px;
				user-select: none;

				.slider {
					flex: 1;
				}

				.title {
					flex-shrink: 0;
					width: 40px;
				}

				&:last-child {
					margin-bottom: 0;
				}

				.number {
					text-align: right;
					flex-shrink: 0;
				}

				// #ifndef MP-ALIPAY || MP-XHS
				.mleft-16 {
					margin-left: 16px !important;
				}

				// #endif
			}
		}

		.contentInput {
			.top {
				@include flex(8px);

				.money {
					@include flex(8px, normal);
					margin-bottom: 16px;
					color: #666;
				}
			}

			.textArea {
				margin-bottom: 12px;

				& ::v-deep .u-textarea {
					border: none;
					padding: 16px;
					background-color: #F5F5F5;
				}

				& ::v-deep .u-textarea__field {
					padding: 0;
					background-color: transparent;
				}

				& ::v-deep .u-textarea__count {
					background-color: transparent !important;
					color: var(--text-color) !important;
				}

				.alipayText {
					height: 88px;
					padding: 16px;
					background-color: #F5F5F5;
					border-radius: 8px;
				}
			}

			.controll {
				@include flex();

				.tip {
					font-size: 12px;
					color: #999;
				}

				.icon {
					width: 24px;
					height: 24px;
					border-radius: 50%;
					display: flex;
					justify-content: center;
					align-items: center;
					overflow: hidden;
				}
			}
		}

		.downProgress {
			@include flex(8px);
		}
	}

	.btnArea {
		padding: 18px 20px;
		background-color: #fff;
		@include flex(12px);

		.btn {
			flex: 1;
			border: 1px solid;
			text-align: center;
			border-radius: 8px;
			padding: 8px 0;
		}
	}
}

.taskName {
	margin-top: 32px;
	padding: 0 12px;

	&>view {
		margin-bottom: 12px;
	}

	.title {
		font-size: 14px;
		font-weight: bold;
		text-align: center;
	}

	.btn {
		border: 1px solid;
		padding: 4px 0;
		border-radius: 8px;
		text-align: center;
	}
}
</style>
